package com.jiejie.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.jiejie.entity.Coupon;
import com.jiejie.entity.CustomerAndCoupon;
import com.jiejie.mapper.CouponMapper;
import com.jiejie.mapper.CustomerAndCouponMapper;
import com.jiejie.service.ICouponService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.rabbitmq.client.Channel;
import lombok.Synchronized;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.rabbit.annotation.RabbitHandler;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.io.ClassPathResource;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.script.DefaultRedisScript;
import org.springframework.scripting.support.ResourceScriptSource;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.PostConstruct;
import javax.annotation.Resource;
import java.io.IOException;
import java.util.*;
import java.util.concurrent.TimeUnit;

/**
 * <p>
 *  服务实现类
 * </p>
 *
 * @author 辰广
 * @since 2022-10-05
 */
@Service
public class CouponServiceImpl extends ServiceImpl<CouponMapper, Coupon> implements ICouponService {
    @Autowired
    private CouponMapper couponMapper;

    @Autowired
    private CustomerAndCouponMapper customerAndCouponMapper;

    @Resource
    private RedisTemplate redisTemplate;

    private DefaultRedisScript<Long> script;

    @PostConstruct
    public void init(){
        script = new DefaultRedisScript<>();
        script.setResultType(Long.class);
        script.setScriptSource(new ResourceScriptSource(new ClassPathResource("niceyoo.lua")));
    }

    @Override
    public Map<Coupon, CustomerAndCoupon> getCoupon(Integer customerId) {
        QueryWrapper wrapper = new QueryWrapper<>();
        wrapper.eq("customer_id",customerId);
        wrapper.orderByDesc("customer_and_coupon_create_time");

        List<CustomerAndCoupon> cac = customerAndCouponMapper.selectList(wrapper);
        Map<Coupon,CustomerAndCoupon> map = new LinkedHashMap<>();

        for (int i=0;i<cac.size();i++){
            Coupon coupon = couponMapper.selectById(cac.get(i).getCouponId());
            map.put(coupon,cac.get(i));
        }
        return map;
    }

    @Override
    public Coupon getCouponfromredisordb(Integer coupon_Id) {
        String key="skillCoupon_"+coupon_Id;
        Coupon coupon=(Coupon) redisTemplate.opsForValue().get(key);
        if(coupon!=null){
            return coupon;
        }
        else {
            coupon=couponMapper.selectById(coupon_Id);
            redisTemplate.opsForValue().set(key,coupon,24, TimeUnit.HOURS);
        }
        return coupon;
    }

    @Override
    public Coupon receiveCoupon(Integer customerId,Integer couponId) {
           Coupon coupon=null;
           String key="skill_coupon_"+couponId;
        System.out.println(key);
           String uuid= UUID.randomUUID().toString().replace("-","");
        System.out.println(uuid+"uuuuuuuuu");
           //获取锁
        System.out.println("==============");
           boolean isLock=redisTemplate.opsForValue().setIfAbsent(key,uuid,10,TimeUnit.SECONDS);
        System.out.println(isLock);
           if(isLock){
               System.out.println("获取锁成功");
               coupon=(Coupon) redisTemplate.opsForValue().get("skillCoupon_"+couponId);
               if(coupon==null)
                   return null;
               //优惠券已被抢光了
               if(coupon.getCouponQuota()==0)
                   return null;
               else {
                   System.out.println("+++coupon===");
                   System.out.println(coupon);
                   coupon.setCouponQuota(coupon.getCouponQuota()-1);
                   redisTemplate.opsForValue().set("skillCoupon_"+couponId,coupon,1,TimeUnit.HOURS);
                   System.out.println(key+"cccccc"+script);
                   Long exexute=(Long) redisTemplate.execute(script,Arrays.asList(key),uuid);
                   return coupon;
               }
           }else {
               //加锁失败
               try {
                   Thread.sleep(100);
                   coupon =(Coupon) redisTemplate.opsForValue().get("skillCoupon_"+couponId);
                   if(coupon != null &&coupon.getCouponQuota()>0) {
                      receiveCoupon(customerId,couponId);
                       return coupon;
                   }else
                       return null;
               } catch (InterruptedException e) {
                   e.printStackTrace();
                   return null;
               }

           }

    }
    @Override
    public void trancouponToDB(){
        Set<String> keys = redisTemplate.keys("skillCoupon"+ "*");
        System.out.println("=========keyss=======");
        System.out.println(keys);
       for(String key:keys){
            System.out.println("=========keyss=======");
           System.out.println("key"+key);
            Coupon coupon=(Coupon)redisTemplate.opsForValue().get(key.toString());
            System.out.println(coupon);
            QueryWrapper<Coupon> wrapper=new QueryWrapper<>();
            wrapper.eq("coupon_id",coupon.getCouponId());
            couponMapper.update(coupon,wrapper);
        }
    }

    @Override
    public List<Coupon> getCouponList() {//数据库中只能有一张券
        List<Coupon> couponList=new ArrayList<>();
        Set<String> keys = redisTemplate.keys("skillCoupon"+ "*");
        System.out.println("=========keyss=======");
        System.out.println(keys);
        for(String key:keys){
            System.out.println("=========keyss=======");
            System.out.println("key"+key);
            Coupon coupon=(Coupon)redisTemplate.opsForValue().get(key.toString());
            System.out.println(coupon);
            couponList.add(coupon);
        }

        if(couponList.size()==0){
            QueryWrapper<Coupon> wrapper=new QueryWrapper<>();
            wrapper.gt("coupon_quota",0);
            couponList=couponMapper.selectList(wrapper);
//        存入Redis
            for (int i=0;i<couponList.size();i++){
                String key="skillCoupon_"+couponList.get(i).getCouponId();
                redisTemplate.opsForValue().setIfAbsent(key,couponList.get(i),24, TimeUnit.HOURS);
            }
        }

        return couponList;
    }

@Override
  public  Map<String,Object> getConfirm(Integer custId){
        QueryWrapper<CustomerAndCoupon> wrapper=new QueryWrapper<>();
        wrapper.eq("customer_id",custId);
        wrapper.eq("customer_and_coupon_status",0);
        List<CustomerAndCoupon> customerAndCouponList=customerAndCouponMapper.selectList(wrapper);
        List<Object> coupandcustId=new ArrayList<>();
        List<Object> couponList=new ArrayList<>();
      for (CustomerAndCoupon c:customerAndCouponList
           ) {
          coupandcustId.add(c.getCustomerAndCouponId());
          couponList.add(couponMapper.selectById(c.getCouponId()));
      }
    System.out.println("====++++++++++++++++++++++++++++++++++++++000");
    System.out.println(coupandcustId);
    System.out.println(couponList);
    Map<String,Object> map=new LinkedHashMap<>();
      map.put("custandcouponId",coupandcustId);
      map.put("couponList",couponList);
        return map;
  }

}
